﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;

namespace RemoteDesktop
{
    class Desktopduplication
    {
        // 假设这是一个封装Windows桌面复制API的类
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

        // [System.Runtime.InteropServices.DllImport("DwmApi.dll")]
        // public static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr source, ref DWM_THUMBNAIL_PROPERTIES props);

        [System.Runtime.InteropServices.DllImport("DwmApi.dll")]
        public static extern int DwmUnregisterThumbnail(IntPtr dest);

        [System.Runtime.InteropServices.DllImport("DwmApi.dll")]
        public static extern int DwmQueryThumbnailSourceSize(IntPtr thumbnail, out Size size);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        [DllImport("gdi32.dll")]
        static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);

        //[System.Runtime.InteropServices.DllImport("DwmApi.dll")]
        // public static extern int DwmUpdateThumbnailProperties(IntPtr dest, ref DWM_THUMBNAIL_PROPERTIES props);
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct Size
        {
            public int cx;
            public int cy;
        }
        public static Bitmap CaptureWindow(IntPtr handle)
        {
            GetWindowRect(handle, out RECT rect);
            int width = rect.Right - rect.Left;
            int height = rect.Bottom - rect.Top;
            Bitmap bitmap = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                IntPtr dc1 = GetWindowDC(handle);
                IntPtr dc2 = g.GetHdc();
                BitBlt(dc2, 0, 0, width, height, dc1, 0, 0, CopyPixelOperation.SourceCopy);
                g.ReleaseHdc(dc2);
                ReleaseDC(handle, dc1);
            }

            return bitmap;
        }
        public static void TextWindow(string txt)
        {
            using(Graphics g = Graphics.FromHwnd(IntPtr.Zero))
            {
                Font font = new Font("Arial", 12, System.Drawing.FontStyle.Bold);
                Brush brush = Brushes.Black;
                g.DrawString(txt, font, brush, new PointF(50, 50));
                g.Dispose();
                ReleaseDC(IntPtr.Zero, IntPtr.Zero);
            }
        }


        //dwFlags参数定义
        public static int MOUSEEVENTF_MOVE = 0x0001;     // 移动鼠标 
        public static int MOUSEEVENTF_LEFTDOWN = 0x0002; //模拟鼠标左键按下 
        public static int MOUSEEVENTF_LEFTUP = 0x0004; //模拟鼠标左键抬起 
        public static int MOUSEEVENTF_RIGHTDOWN = 0x0008; //模拟鼠标右键按下 
        public static int MOUSEEVENTF_RIGHTUP = 0x0010; //模拟鼠标右键抬起 
        public static int MOUSEEVENTF_MIDDLEDOWN = 0x0020;// 模拟鼠标中键按下 在这里插入代码片
        public static int MOUSEEVENTF_MIDDLEUP = 0x0040; //模拟鼠标中键抬起 
        public static int MOUSEEVENTF_ABSOLUTE = 0x8000; //标示是否采用绝对坐标。不采用绝对坐标的话（0,0）表示的是该鼠标当时的位置   

        //是鼠标自动移动到某个位置
        [DllImport("user32.dll", EntryPoint = "SetCursorPos")]
        public extern static bool SetCursorPos(int x, int y);
        //获取鼠标当前的位置
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;
        }
        [DllImport("User32")]
        public extern static bool GetCursorPos(out POINT p);
        //是否显示鼠标箭头
        [DllImport("User32")]
        public extern static int ShowCursor(bool bShow);
        //调用系统函数 模拟鼠标事件函数
        [DllImport("user32", EntryPoint = "mouse_event")]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        #region bVk参数 常量定义
        public const byte vbKeyLButton = 0x1;    // 鼠标左键
        public const byte vbKeyRButton = 0x2;    // 鼠标右键
        public const byte vbKeyCancel = 0x3;     // CANCEL 键
        public const byte vbKeyMButton = 0x4;    // 鼠标中键
        public const byte vbKeyBack = 0x8;       // BACKSPACE 键  空格键
        public const byte vbKeyTab = 0x9;        // TAB 键
        public const byte vbKeyClear = 0xC;      // CLEAR 键
        public const byte vbKeyReturn = 0xD;     // ENTER 键
        public const byte vbKeyShift = 0x10;     // SHIFT 键
        public const byte vbKeyControl = 0x11;   // CTRL 键
        public const byte vbKeyAlt = 18;         // Alt 键  (键码18)
        public const byte vbKeyMenu = 0x12;      // MENU 键
        public const byte vbKeyPause = 0x13;     // PAUSE 键
        public const byte vbKeyCapital = 0x14;   // CAPS LOCK 键
        public const byte vbKeyEscape = 0x1B;    // ESC 键
        public const byte vbKeySpace = 0x20;     // SPACEBAR 键
        public const byte vbKeyPageUp = 0x21;    // PAGE UP 键
        public const byte vbKeyEnd = 0x23;       // End 键
        public const byte vbKeyHome = 0x24;      // HOME 键
        public const byte vbKeyLeft = 0x25;      // LEFT ARROW 键
        public const byte vbKeyUp = 0x26;        // UP ARROW 键
        public const byte vbKeyRight = 0x27;     // RIGHT ARROW 键
        public const byte vbKeyDown = 0x28;      // DOWN ARROW 键
        public const byte vbKeySelect = 0x29;    // Select 键
        public const byte vbKeyPrint = 0x2A;     // PRINT SCREEN 键
        public const byte vbKeyExecute = 0x2B;   // EXECUTE 键
        public const byte vbKeySnapshot = 0x2C;  // SNAPSHOT 键
        public const byte vbKeyDelete = 0x2E;    // Delete 键
        public const byte vbKeyHelp = 0x2F;      // HELP 键
        public const byte vbKeyNumlock = 0x90;   // NUM LOCK 键

        //常用键 字母键A到Z
        public const byte vbKeyA = 65;
        public const byte vbKeyB = 66;
        public const byte vbKeyC = 67;
        public const byte vbKeyD = 68;
        public const byte vbKeyE = 69;
        public const byte vbKeyF = 70;
        public const byte vbKeyG = 71;
        public const byte vbKeyH = 72;
        public const byte vbKeyI = 73;
        public const byte vbKeyJ = 74;
        public const byte vbKeyK = 75;
        public const byte vbKeyL = 76;
        public const byte vbKeyM = 77;
        public const byte vbKeyN = 78;
        public const byte vbKeyO = 79;
        public const byte vbKeyP = 80;
        public const byte vbKeyQ = 81;
        public const byte vbKeyR = 82;
        public const byte vbKeyS = 83;
        public const byte vbKeyT = 84;
        public const byte vbKeyU = 85;
        public const byte vbKeyV = 86;
        public const byte vbKeyW = 87;
        public const byte vbKeyX = 88;
        public const byte vbKeyY = 89;
        public const byte vbKeyZ = 90;

        //数字键盘0到9
        public const byte vbKey0 = 48;    // 0 键
        public const byte vbKey1 = 49;    // 1 键
        public const byte vbKey2 = 50;    // 2 键
        public const byte vbKey3 = 51;    // 3 键
        public const byte vbKey4 = 52;    // 4 键
        public const byte vbKey5 = 53;    // 5 键
        public const byte vbKey6 = 54;    // 6 键
        public const byte vbKey7 = 55;    // 7 键
        public const byte vbKey8 = 56;    // 8 键
        public const byte vbKey9 = 57;    // 9 键


        public const byte vbKeyNumpad0 = 0x60;    //0 键
        public const byte vbKeyNumpad1 = 0x61;    //1 键
        public const byte vbKeyNumpad2 = 0x62;    //2 键
        public const byte vbKeyNumpad3 = 0x63;    //3 键
        public const byte vbKeyNumpad4 = 0x64;    //4 键
        public const byte vbKeyNumpad5 = 0x65;    //5 键
        public const byte vbKeyNumpad6 = 0x66;    //6 键
        public const byte vbKeyNumpad7 = 0x67;    //7 键
        public const byte vbKeyNumpad8 = 0x68;    //8 键
        public const byte vbKeyNumpad9 = 0x69;    //9 键
        public const byte vbKeyMultiply = 0x6A;   // MULTIPLICATIONSIGN(*)键
        public const byte vbKeyAdd = 0x6B;        // PLUS SIGN(+) 键
        public const byte vbKeySeparator = 0x6C;  // ENTER 键
        public const byte vbKeySubtract = 0x6D;   // MINUS SIGN(-) 键
        public const byte vbKeyDecimal = 0x6E;    // DECIMAL POINT(.) 键
        public const byte vbKeyDivide = 0x6F;     // DIVISION SIGN(/) 键


        //F1到F12按键
        public const byte vbKeyF1 = 0x70;   //F1 键
        public const byte vbKeyF2 = 0x71;   //F2 键
        public const byte vbKeyF3 = 0x72;   //F3 键
        public const byte vbKeyF4 = 0x73;   //F4 键
        public const byte vbKeyF5 = 0x74;   //F5 键
        public const byte vbKeyF6 = 0x75;   //F6 键
        public const byte vbKeyF7 = 0x76;   //F7 键
        public const byte vbKeyF8 = 0x77;   //F8 键
        public const byte vbKeyF9 = 0x78;   //F9 键
        public const byte vbKeyF10 = 0x79;  //F10 键
        public const byte vbKeyF11 = 0x7A;  //F11 键
        public const byte vbKeyF12 = 0x7B;  //F12 键
        #endregion

        #region 引用win32api方法

        /// <summary>
        /// 导入模拟键盘的方法
        /// </summary>
        /// <param name="bVk" >按键的虚拟键值</param>
        /// <param name= "bScan" >扫描码，一般不用设置，用0代替就行</param>
        /// <param name= "dwFlags" >选项标志：0：表示按下，2：表示松开</param>
        /// <param name= "dwExtraInfo">一般设置为0</param>
        [DllImport("user32.dll")]
        public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

        #endregion

        public static void HideTaskbarAndSetFullScreen(Window wd)
        {
            // 获取窗口的句柄
            IntPtr windowHandle = new WindowInteropHelper(wd).Handle;

            // 设置窗口样式
            int windowStyle = GetWindowLong(windowHandle, GWL_STYLE);
            SetWindowLong(windowHandle, GWL_STYLE, windowStyle & ~WS_CAPTION & ~WS_THICKFRAME);

            // 设置窗口大小以全屏
            SetWindowPos(windowHandle, IntPtr.Zero, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, SWP_SHOWWINDOW);
        }

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll")]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        private const int GWL_STYLE = -16;
        private const int WS_CAPTION = 0xC00000;
        private const int WS_THICKFRAME = 0x40000;
        private const uint SWP_SHOWWINDOW = 0x0040;

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern IntPtr SetCapture(IntPtr hWnd);

        [DllImport("user32.dll")]
        public static extern IntPtr GetCapture();

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool ReleaseCapture();
        public static string RunCmd(string command, string dir = "")//运行一个cmd命令
        {
            Process p = new Process();
            if (dir != "")
            {
                p.StartInfo.WorkingDirectory = dir;  // "c:\\";    // 工作目录
            }
            p.StartInfo.FileName = "cmd.exe";           // 程序名
            p.StartInfo.Arguments = "/c " + command;    // 执行参数
            p.StartInfo.UseShellExecute = false;        // 关闭Shell的使用
            p.StartInfo.RedirectStandardInput = true;   // 重定向标准输入
            p.StartInfo.RedirectStandardOutput = true;  // 重定向标准输出
            p.StartInfo.RedirectStandardError = true;   // 重定向错误输出
            p.StartInfo.CreateNoWindow = true;          // 设置不显示窗口
            p.Start();   //启动
            //p.StandardInput.WriteLine(command);       // 也可以用这种方式输入要执行的命令
            //p.StandardInput.WriteLine("exit");        // 不过要记得加上Exit，要不然下一行执行的时候会出错
            string err = p.StandardError.ReadToEnd();
            string txt = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            p.Close();
            p.Dispose();
            return txt + err;        // 从输出流取得命令执行结果
        }

        [DllImport("user32.dll")]
        static extern bool GetCursorInfo(out CURSORINFO pci);

        [DllImport("user32.dll")]
        public static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);

        [DllImport("user32.dll")]
        public static extern IntPtr GetCursor();
        [StructLayout(LayoutKind.Sequential)]
        struct CURSORINFO
        {
            public int cbSize;
            public int flags;
            public IntPtr hCursor;
            public POINT ptScreenPos;
        }
 
        public static Bitmap TakeScreenshotWithCursor()
        {
            // 获取屏幕截图
            Bitmap screenBmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics screenGraphics = Graphics.FromImage(screenBmp);
            screenGraphics.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);

            // 获取并绘制鼠标光标
            CURSORINFO cursorInfo = new CURSORINFO();
            cursorInfo.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
            GetCursorInfo(out cursorInfo);

            if (cursorInfo.hCursor != IntPtr.Zero)
            {
                //IntPtr cursorHandle = GetCursor();
                Cursor.Current = Cursors.Default;
                IntPtr cursorHandle = Cursor.Current.Handle;
                screenGraphics.DrawIcon(Icon.FromHandle(cursorHandle),cursorInfo.ptScreenPos.X, cursorInfo.ptScreenPos.Y);
            }

            return screenBmp;
        }
        public static Bitmap CaptureScreen()
        {
            IntPtr desktopPtr = GetDesktopWindow();
            IntPtr dcPtr = GetWindowDC(desktopPtr);

            Rectangle rect = new Rectangle(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                IntPtr gDC = g.GetHdc();
                BitBlt(gDC, 0, 0, bmp.Width, bmp.Height, dcPtr, 0, 0, CopyPixelOperation.SourceCopy);
                g.ReleaseHdc(gDC);
            }

            ReleaseDC(desktopPtr, dcPtr);
            return bmp;
        }
    }

}